
require 'rubygems'
require 'mechanize'
require 'hpricot'

# TODO: クラスごとにファイルに分ける
# TODO: timeline の取得処理にコードのダブりを調整

class Wassr
  class Message
    attr_accessor :username, :message, :permalink, :date, :favorite, :is_private

    def initialize
      @favorite = []
    end
  end

  class Favorite
    attr_accessor :username
  end

  class API
  end

  def initialize
    @is_logined = false
  end

  def login(username, passwd)
    @agent = WWW::Mechanize.new

    page = @agent.get('http://wassr.jp/')

    form = page.forms.name('LoginForm').first
    form.login_id = username
    form.login_pw = passwd

    @user_top_page = @agent.submit(form)

    @is_logined = true

    true
  end

  def timeline(limit_date = nil)
    messages = []

    Wassr::walk_timeline_page(@agent, @user_top_page, limit_date)
  end

  def self.public_timeline(limit_date = nil)
    agent = WWW::Mechanize.new

    page = agent.get("http://wassr.jp/timeline/public")

    Wassr::walk_timeline_page(agent, page, limit_date)
  end

  def self.favorites(username = nil, limit_date = nil)
    return []  if username.nil?

    agent = WWW::Mechanize.new

    page = agent.get("http://wassr.jp/user/#{username}/favorites")

    Wassr::walk_timeline_page(agent, page, limit_date)
  end


  def self.walk_timeline_page(agent, page, limit_date = nil)
    messages = []

    timeline_page = page

    while true
      m = Wassr::parse_html_page(timeline_page.body)

      messages.concat(m)

      # TODO: ページ移動中に発言が流れる可能性があるため、ユニーク処理が必要

      next_link = timeline_page.at('#PagerNextLink')
      if next_link.nil?
        break
      end
      puts "debug: -> #{next_link[:href]}"

      # TODO: いらない日付の発言は切るように
      if !limit_date.nil? && m.last.date <= limit_date
        break
      end

      select(nil, nil, nil, 0.75)

      timeline_page = agent.click next_link
    end

    messages
  end

  def self.parse_html_page(html)
    messages = []

    doc = Hpricot(html)

    (doc/"div[@class='OneMsg xfolkentry']").each do |elem|
      msg = Wassr::Message.new

      # TODO: HTML 要素がなかった場合のエラー処理
      msg.username = elem.at("div.messagefoot_container > p.messagefoot > a.MsgUserName").inner_text # username
      msg.is_private = elem.at("span[@class='friends_only_banner']").nil? # private
      msg.permalink = elem.at("div.messagefoot_container > p.messagefoot > a.MsgDateTime")[:href]   # permalink
      msg.message = elem.at("p[@class='message description']").inner_text # message
      date = elem.at("div.messagefoot_container > p.messagefoot > a.MsgDateTime").inner_text # date

      favorite_elems = elem.at("div.favorite_list")
      unless favorite_elems.nil?
        (favorite_elems/"a").each do |favorite_elem|
          favorite = Wassr::Favorite.new
          favorite.username = favorite_elem[:title]

          msg.favorite << favorite
        end
      end

      msg.date = Time.parse(date)
      msg.message = msg.message.gsub(/(^\s+)|(\n$)|(\r\n$)/m, '')

      messages << msg
    end

    messages
  end
end

__END__
#
# 2008/10/03
# * 'Next' リンクの抽出条件を変更
#
# 2008/09/28
# * Wassr::Message に permalink, favorite を追加
# * Wassr::parse_html_page permalink, favorite の解析処理を追加
# * Wassr::Message message の末尾の改行を削除する処理を追加
# * Wassr::walk_timeline_page timeline ページを走査して解析するメソッドを追加
# * Wassr#new 追加
# * Wassr is_logined を追加
#

